package cn.yuanqiao.manage.service.impl;

import cn.yuanqiao.common.constant.CacheConstants;
import cn.yuanqiao.common.constant.SecurityConstants;
import cn.yuanqiao.common.core.domain.R;
import cn.yuanqiao.common.core.domain.entity.SysRole;
import cn.yuanqiao.common.core.domain.entity.SysUser;
import cn.yuanqiao.common.exception.ServiceException;
import cn.yuanqiao.common.core.text.Convert;
import cn.yuanqiao.common.utils.DateUtils;
import cn.yuanqiao.common.utils.StringUtils;
import cn.yuanqiao.common.utils.bean.BeanValidators;
import cn.yuanqiao.common.service.RedisService;
import cn.yuanqiao.common.utils.SecurityUtils;
import cn.yuanqiao.manage.constant.RoleConstant;
import cn.yuanqiao.manage.domain.ManageFonds;
import cn.yuanqiao.manage.domain.ManageTenant;
import cn.yuanqiao.manage.mapper.ManageFondsMapper;
import cn.yuanqiao.manage.mapper.ManageTenantMapper;
import cn.yuanqiao.manage.model.ManageSysModel;
import cn.yuanqiao.manage.service.IManageSysService;
import cn.yuanqiao.manage.service.IManageTenantService;

import cn.yuanqiao.system.service.ISysMenuService;
import cn.yuanqiao.system.service.ISysRoleService;
import cn.yuanqiao.system.service.ISysUserService;
import com.sun.org.apache.xpath.internal.operations.Bool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.Validator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 租户信息Service业务层处理
 *
 * @author yuanqiao
 * @date 2023-06-07
 */
@Service
public class ManageTenantServiceImpl implements IManageTenantService
{
    private static final Logger log = LoggerFactory.getLogger(ManageTenantServiceImpl.class);
    @Autowired
    private ManageTenantMapper manageTenantMapper;
    @Autowired
    protected Validator validator;
    @Autowired
    private RedisService redisService;

    @Autowired
    private ManageFondsMapper manageFondsMapper;
    @Autowired
    private ISysUserService remoteUserService;

    @Autowired
    private ISysRoleService sysRoleService;

    @Resource
    private ISysMenuService sysMenuService;
    @Value("${encryption}")
    private String encryption;
    /**
     * 查询租户信息
     *
     * @param ID 租户信息主键
     * @return 租户信息
     */
    @Override
    public ManageTenant selectManageTenantByID(String ID)
    {
        return manageTenantMapper.selectManageTenantByID(ID);
    }
    @Override
    public ManageTenant selectUserByLoginName(String loginName)
    {
        return manageTenantMapper.selectUserByLoginName(loginName);
    }

    /**
     * 查询租户信息列表
     *
     * @param manageTenant 租户信息
     * @return 租户信息
     */
    @Override
    public List<ManageTenant> selectManageTenantList(ManageTenant manageTenant)
    {
        String userName = manageTenant.getUserName();
        if(StringUtils.isNotEmpty(userName) && !"null".equals(userName) && userName.contains("_")){
            userName = userName.replace("_","\\_");
            manageTenant.setUserName(userName);
        }
        return manageTenantMapper.selectManageTenantList(manageTenant);
    }

    /**
     * 新增租户信息
     *
     * @param manageTenant 租户信息
     * @return 结果
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public int insertManageTenant(ManageTenant manageTenant)
    {
        //String loginName = manageTenant.getLoginName();
        String tenantCode = manageTenant.getTenantCode();
        String[] sysprefix = RoleConstant.SYSPREFIX;
        List<String> sysPrefixStr = Arrays.asList(sysprefix);
        if(sysPrefixStr.contains(tenantCode.toUpperCase())){
            throw new ServiceException("系统编码禁止使用");
        }
        //ManageTenant u = manageTenantMapper.selectTenantByLoginName(loginName);
        ManageTenant u1 = manageTenantMapper.selectTenantByTenantCode(manageTenant.getTenantCode());
        /*if (!StringUtils.isNull(u)){
            throw new ServiceException("账号"+loginName+"已存在");
        }*/
        if (!StringUtils.isNull(u1)){
            throw new ServiceException("租户编码"+tenantCode+"已存在");
        }
        if("true".equals(manageTenant.getIsManagerDept())){
            ManageTenant u2 = manageTenantMapper.selectTenantByManager("true");
            if(u2!=null){
                throw new ServiceException("已存在管理单位，管理单位有且只有一个，当前管理单位是："+u2.getRegisteredUnit());
            }
        }

        manageTenant.setCreateTime(DateUtils.getNowDate());
        manageTenant.setCreateBy(SecurityUtils.getUsername());
        //新增租户的同时绑定一个全宗号
        String fondsCode = manageTenant.getFondsCode();
        //if(!StringUtils.isEmpty(fondsCode) && !"null".equals(fondsCode)){
        ManageFonds manageFonds1 = new ManageFonds();
        manageFonds1.setFondsCode(fondsCode);
        manageFonds1.setTenantCode(tenantCode);
        ManageFonds manageFonds = new ManageFonds();
        manageFonds.setStatus("0");
        manageFonds.setFondsCode(fondsCode);
        manageFonds.setFondsName(manageTenant.getRegisteredUnit());
        manageFonds.setCreateBy(SecurityUtils.getUsername());
        manageFonds.setCreateTime(DateUtils.getNowDate());
        manageFonds.setTenantCode(tenantCode);
        manageFondsMapper.insertManageFonds(manageFonds);
        List<ManageFonds> manageFonds3 = manageFondsMapper.selectManageFondsList(manageFonds1);
        ManageFonds manageFonds4 = manageFonds3.get(0);
        Long id = manageFonds4.getId();
        //}
        manageTenant.setFondsCodeId(id);
        int i = manageTenantMapper.insertManageTenant(manageTenant);
        //新建租户后 自动添加三员信息
        addSysInfo(tenantCode);
        return i;
    }

    public void addSysInfo(String tenantCode){
        Boolean flag = sysMenuService.copyMenuByTenantCode(tenantCode);
        List<SysRole> sysRoleList = ManageSysModel.getSysRoleList(tenantCode);
        List<SysUser> sysUserList = ManageSysModel.getSysUserList(tenantCode);
        for(int i=0;i<sysRoleList.size();i++){
            SysRole sysRole = sysRoleList.get(i);
            sysRoleService.insertRole(sysRole);
            sysRoleService.updateRole(sysRole);
        }
        for(int i=0;i<sysUserList.size();i++){
            SysUser sysUser = sysUserList.get(i);
            //将sysUser里的tenantCode和userName用_拼接起来，作为roleKey，从sysRoleList里找出对应的sysRole的id
            String roleKey = sysUser.getTenantCode()+"_"+sysUser.getUserName();
            List<SysRole> collect = sysRoleList.stream()
                    .filter(sysRole -> sysRole.getRoleKey().equals(roleKey))
                    .collect(Collectors.toList());
            sysUser.setRoles(collect);
            sysUser.setRoleIds(collect.stream()
                    .map(SysRole::getRoleId)
                    .collect(Collectors.toList())
                    .toArray(new Long[0]));
            remoteUserService.insertUser(sysUser);
            remoteUserService.updateUser(sysUser);
        }
    }

    /**
     * 修改租户信息
     *
     * @param manageTenant 租户信息
     * @return 结果
     */
    @Override
    public int updateManageTenant(ManageTenant manageTenant)
    {
        /*manageTenant.setUpdateTime(DateUtils.getNowDate());
        manageTenant.setUpdateBy(SecurityUtils.getUsername());
        String ps = manageTenantMapper.getPassWordById(manageTenant.getId());
        if(!ps.equals(manageTenant.getPassWord())) manageTenant.setPassWord(SecurityUtils.encryptPassword(manageTenant.getPassWord()));
        return manageTenantMapper.updateManageTenant(manageTenant);*/


        manageTenant.setUpdateTime(DateUtils.getNowDate());
        manageTenant.setUpdateBy(SecurityUtils.getUsername());
        //String ps = manageTenantMapper.getPassWordById(manageTenant.getId());
        //if(!ps.equals(manageTenant.getPassWord())) manageTenant.setPassWord(SecurityUtils.encryptPassword(manageTenant.getPassWord()));
        if("true".equals(manageTenant.getIsManagerDept())){
            ManageTenant u2 = manageTenantMapper.selectTenantByManager("true");
            if(u2!=null && u2.getId().longValue() != manageTenant.getId().longValue()){
                throw new ServiceException("已存在管理单位，管理单位有且只有一个，当前管理单位是："+u2.getRegisteredUnit());
            }
        }

        //修改租户时 同步修改对应的全宗
        String fondsCode = manageTenant.getFondsCode();
        Long fondsCodeId = manageTenant.getFondsCodeId();
        String registeredUnit = manageTenant.getRegisteredUnit();

        ManageTenant manageTenant1 = manageTenantMapper.selectManageTenantByID(String.valueOf(manageTenant.getId()));
        String fondsCode1 = manageTenant1.getFondsCode();
        if(!fondsCode.equals(fondsCode1)){
            ManageFonds manageFonds1 = new ManageFonds();
            manageFonds1.setFondsCode(fondsCode);
            manageFonds1.setTenantCode(manageTenant.getTenantCode());
            List<ManageFonds> manageFonds2 = manageFondsMapper.selectManageFondsList(manageFonds1);
            if(manageFonds2.size()!=0){
                throw new ServiceException("全宗号已存在");
            }
        }

        ManageFonds manageFonds3 = new ManageFonds();
        manageFonds3.setFondsName(registeredUnit);
        manageFonds3.setFondsCode(fondsCode);
        manageFonds3.setId(fondsCodeId);
        manageFondsMapper.updateManageFonds(manageFonds3);
        return manageTenantMapper.updateManageTenant(manageTenant);
    }
    @Override
    public int updateManageTenantStatus(ManageTenant manageTenant)
    {
        return manageTenantMapper.updateManageTenant(manageTenant);
    }

    /**
     * 批量删除租户信息
     *
     * @param IDs 需要删除的租户信息主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteManageTenantByIDs(String[] IDs)
    {
        ManageTenant manageTenant = manageTenantMapper.selectManageTenantByID(IDs[0]);
        int i = manageTenantMapper.deleteManageTenantByIDs(IDs);
        String fondsCode = manageTenant.getFondsCode();
        String tenantCode = manageTenant.getTenantCode();
        ManageFonds manageFonds = new ManageFonds();
        manageFonds.setFondsCode(fondsCode);
        manageFonds.setTenantCode(tenantCode);
        List<ManageFonds> manageFonds1 = manageFondsMapper.selectManageFondsList(manageFonds);
        if(null!=manageFonds1 && manageFonds1.size()==1){
            ManageFonds manageFonds2 = manageFonds1.get(0);
            manageFondsMapper.deleteManageFondsByID(manageFonds2.getId().toString());
        }
        List<Long> sysUsers = remoteUserService.selectUserByTenantCode(manageTenant.getTenantCode());
        List<Long> sysRoles = sysRoleService.selectRoleListByTenantCode(manageTenant.getTenantCode());
        Long[] l = {};
        Long[] l2 = {};
        Long[] lo = sysUsers.toArray(l);
        Long[] lo2 = sysRoles.toArray(l2);
        remoteUserService.deleteUserByIds(lo);
        sysRoleService.deleteRoleByIds(lo2);
        sysMenuService.deleteMenuByTenantCode(manageTenant.getTenantCode());
        return i;
    }

    /**
     * 删除租户信息信息
     *
     * @param ID 租户信息主键
     * @return 结果
     */
    @Override
    public int deleteManageTenantByID(String ID)
    {
        return manageTenantMapper.deleteManageTenantByID(ID);
    }

    @Override
    public String importUser(List<ManageTenant> userList, Boolean isUpdateSupport, String operName)
    {
        if (StringUtils.isNull(userList) || userList.size() == 0)
        {
            throw new ServiceException("导入租户数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();

        //获取默认密码
        String password = Convert.toStr(redisService.getCacheObject(getCacheKey("sys.user.initPassword")));
        if (!StringUtils.isNotEmpty(password)) password = "123456";

        for (ManageTenant user : userList)
        {
            try
            {
                // 验证是否存在这个用户
                ManageTenant u = manageTenantMapper.selectTenantByLoginName(user.getLoginName());
                ManageTenant u1 = manageTenantMapper.selectTenantByTenantCode(user.getTenantCode());
                if (StringUtils.isNull(u) && StringUtils.isNull(u1))
                {
                    user.setPassWord(SecurityUtils.encryptPassword(password,encryption));
                    user.setCreateBy(operName);
                    BeanValidators.validateWithException(validator, user);

                    String tenantCode = user.getTenantCode();
                    String[] sysprefix = RoleConstant.SYSPREFIX;
                    List<String> sysPrefixStr = Arrays.asList(sysprefix);
                    if(sysPrefixStr.contains(tenantCode.toUpperCase())){
                        //throw new ServiceException("系统编码禁止使用");
                        failureNum++;
                        failureMsg.append("<br/>" + failureNum + "、编码 " + user.getTenantCode() + " 禁止使用");
                        continue;
                    }
                    if(!tenantCode.matches("^[A-Z]+$")){
                        failureNum++;
                        failureMsg.append("<br/>" + failureNum + "、编码 " + user.getTenantCode() + " 不是全大写英文字母组成，禁止使用");
                        continue;
                    }

                    String fondsCode = user.getFondsCode();
                    //if(!StringUtils.isEmpty(fondsCode) && !"null".equals(fondsCode)){
                    ManageFonds manageFonds1 = new ManageFonds();
                    manageFonds1.setFondsCode(fondsCode);
                    manageFonds1.setTenantCode(tenantCode);
                    ManageFonds manageFonds = new ManageFonds();
                    manageFonds.setStatus("0");
                    manageFonds.setFondsCode(fondsCode);
                    manageFonds.setFondsName(user.getRegisteredUnit());
                    manageFonds.setCreateBy(SecurityUtils.getUsername());
                    manageFonds.setCreateTime(DateUtils.getNowDate());
                    manageFonds.setTenantCode(tenantCode);
                    manageFondsMapper.insertManageFonds(manageFonds);
                    List<ManageFonds> manageFonds3 = manageFondsMapper.selectManageFondsList(manageFonds1);
                    ManageFonds manageFonds4 = manageFonds3.get(0);
                    Long id = manageFonds4.getId();
                    //}
                    user.setFondsCodeId(id);


                    manageTenantMapper.insertManageTenant(user);
                    //新建租户后 自动添加三员信息
                    addSysInfo(user.getTenantCode());
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、用户名 " + user.getUserName() + " 导入成功");

                } else if(!StringUtils.isNull(u))
                {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、用户名 " + user.getUserName() + " 已存在");
                }else if(!StringUtils.isNull(u1)){
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、租户编码 " + user.getTenantCode() + " 已存在");
                }
            }
            catch (Exception e)
            {
                failureNum++;
                String msg = "<br/>" + failureNum + "、用户名 " + user.getUserName() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }
        if (failureNum > 0)
        {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        }
        else
        {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    @Override
    public int isExistTable(String tableName) {
        return manageTenantMapper.isExistTable(tableName);
    }

    @Override
    public ManageTenant selectTenantByManager(String isManagerDept) {
        return manageTenantMapper.selectTenantByManager(isManagerDept);
    }

    private String getCacheKey(String configKey)
    {
        return CacheConstants.SYS_CONFIG_KEY + configKey;
    }
}
